/**
 * Title:       StringMessage.java
 * Copyright:   Copyright (c) 1996-2004 The Agent Factory Working Group. All rights reserved.
 * Licence:     This file is free software; you can redistribute it and/or modify
 *              it under the terms of the GNU Lesser General Public License as published by
 *              the Free Software Foundation; either version 2.1, or (at your option)
 *              any later version.
 *
 *              This file is distributed in the hope that it will be useful,
 *              but WITHOUT ANY WARRANTY; without even the implied warranty of
 *              MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *              GNU Lesser General Public License for more details.
 *
 *              You should have received a copy of the GNU Lesser General Public License
 *              along with Agent Factory; see the file COPYING.  If not, write to
 *              the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *              Boston, MA 02111-1307, USA.
 */
package com.agentfactory.platform.mts;

import com.agentfactory.platform.core.AgentID;
import java.util.ArrayList;

/**
 * Implementation of FIPA ACL Messaging Representation in String.
 *
 * @author  Rem Collier
 */
public class StringMessage extends Message {
    /** Creates a new instance of StringMessage */
    private StringMessage() {
        receivers = new ArrayList();
    }
    
    public static StringMessage newInstance() {
        return new StringMessage();
    }
    
    /**
     * Factory method that is responsible for the creation of a StringMessage
     * object based upon the String passed as a parameter.
     *
     * @param content the message in a string format
     * @return the message as a StringMessage object
     */
    public static StringMessage newInstance(String content) {
        StringMessage message = new StringMessage();
        // Convert the string to FIPA content, and then process...
        FIPAContent parts = FIPAContent.newInstance(content);
        message.setPerformative(parts.getCommand().toLowerCase());

        // Temporary variables
        ArrayList receivers = null;
        FIPAContent part = null;
        // Now process the remaining tokens
        for (int i = 0; i < parts.size(); i++) {
            part = parts.get(i);
            if (part.getCommand().equals(":sender")) {
                message.setSender(new AgentID(parts.get(++i)));
            } else if (part.getCommand().equals(":receiver")) {
                part = parts.get(++i);
                for (int j=0; j < part.size(); j++) {
                    message.receivers.add(new AgentID(part.get(j)));
                }
            } else if (part.getCommand().equals(":content-length")) {
                message.setContentLength(Integer.parseInt(parts.get(++i).toString()));
            } else if (part.getCommand().equals(":reply-with")) {
                message.setReplyWith(parts.get(++i).toString());
            } else if (part.getCommand().equals(":reply-to")) {
                message.setReplyTo(new AgentID(parts.get(++i)));
            } else if (part.getCommand().equals(":language")) {
                message.setLanguage(parts.get(++i).toString());
            } else if (part.getCommand().equals(":ontology")) {
                message.setOntology(parts.get(++i).toString());
            } else if (part.getCommand().equals(":content")) {
                message.setContent(parts.get(++i).toString());
            } else if (part.getCommand().equals(":protocol")) {
                message.setProtocol(parts.get(++i).toString());
            }
        }
        
        return message;
    }

    /**
     * This method parses a message token to extract an agent identifier.
     *
     * @param aidToken the message token to be parsed
     * @return an AgentID object or null
     */
    private static AgentID parseAgentID(String aidToken) {
        String name = null;
        ArrayList addresses = new ArrayList();
        ArrayList resolvers = new ArrayList();
        
        // Tokenize the ALPHAAgent-identifier string
        ArrayList aidTokens = FIPAHelper.getMessageTokens(aidToken);
        int length = aidTokens.size();
        
       
        // Check that the first token is agent-identifier
        if (!aidTokens.get(0).equals("agent-identifier")) {
            return null;
        }
        
        for (int i = 1; i < length; i++) {
            if (aidTokens.get(i).equals(":name")) {
                name = (String) aidTokens.get(++i);
            } else if (aidTokens.get(i).equals(":addresses")) {
                addresses = FIPAHelper.getMessageTokens((String) aidTokens.get(++i));
            }
        }
        
        // Remove sequence from the list of addresses
        if (addresses.size() > 0) {
            addresses.remove("sequence");
        }
                
        return new AgentID(name, addresses, resolvers);
    }
    
    public String toFIPAString() {
        StringBuffer buf = new StringBuffer();
        buf.
            append("(").
            append(performative);
        
        buf.
            append(" :sender ").
            append(sender.toFIPAString()).
            append(" :receiver (set");
        
        for (int i = 0; i < receivers.size(); i++) {
            buf.
                append(" ").
                append(((AgentID) receivers.get(i)).toFIPAString());
        }

        buf.append(")");
        
        if (contentLength > 0) {
            buf.append(" :content-length ").append(contentLength);
        }
        
        if (replyWith != null) {
            buf.append(" :reply-with ").append(replyWith);
        }
        
        if (replyTo != null) {
            buf.append(" :reply-to ").append(replyTo.toFIPAString());
        }
        
        if (language != null) {
            buf.append(" :language ").append(language);
        }
        
        if (ontology != null) {
            buf.append(" :ontology ").append(ontology);
        }
        
        if (content != null) {
            buf.append(" :content ").append(content);
        }
        
        if (protocol != null) {
            buf.append(" :protocol ").append(protocol);
        }
        
        buf.append(")");
        
        return buf.toString();
    }
    
    public String toString() {
        return toFIPAString();
    }
    
    public String getAclRepresentation() {
        return "fipa.acl.rep.string.std";
    }
    
    public String getPayloadEncoding() {
        return "US-ASCII";
    }
    
/**************************************************************************
 * Test Code
 **************************************************************************/
/*
    public static void main(String[] args) {
        String message = "(inform :sender (agent-identifier :name rem :addresses (sequence http://localhost/acc)) " +
        ":receiver (set (agent-identifier :name bob :addresses (sequence http://localhost/acc))) " +
        ":content \"test content\")";
        System.out.println("Message: " + StringMessage.newInstance2(message));
    }
 */
}
